www.gusucode.com > VC++ 二进制文件差异对比工具 > VC++ 二进制文件差异对比工具/gusucode/FCompare/FCompareDlg.cpp
//Download by http://www.NewXing.com // FCompareDlg.cpp : implementation file // (c) Codeguru & friends // Coded by Antonio Tejada Lacaci. 1999 // atejada@espanet.com // #include "stdafx.h" #include "FCompare.h" #include "FCompareDlg.h" #include "DirDialog.h" #include <Shlwapi.h> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About #include "HyperLink.h" class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; CHyperLink m_urlHomepage; CHyperLink m_urlCodeguru; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) DDX_Control(pDX, URL_HOMEPAGE, m_urlHomepage); DDX_Control(pDX, URL_CODEGURU, m_urlCodeguru); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CFCompareDlg dialog CFCompareDlg::CFCompareDlg(CWnd* pParent /*=NULL*/) : CDialog(CFCompareDlg::IDD, pParent) { //{{AFX_DATA_INIT(CFCompareDlg) m_bRecurse = FALSE; m_nMatchCriteria = 0; m_dwUpto = 0; m_strAllowedMasks = _T("*.*"); m_strDirectory = _T(""); m_bCompareDuplicates = FALSE; //}}AFX_DATA_INIT m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); // Flags m_bExit = FALSE; m_bAbort = FALSE; m_bAddInProgress = FALSE; m_bFillInProgress = FALSE; m_bCompareInProgress = FALSE; m_bsState = BS_IDLE; // Logical data m_msaMatchedInfos.SetSize(0,20); } void CFCompareDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CFCompareDlg) DDX_Control(pDX, LBL_STATUS, m_lblStatus); DDX_Control(pDX, LBL_TARGETFILES, m_lblTargetFiles); DDX_Control(pDX, LBL_SOURCEFILES, m_lblSourceFiles); DDX_Control(pDX, LBL_MATCHEDFILES, m_lblMatchedFiles); DDX_Control(pDX, LST_MATCHEDFILES, m_lstMatchedFiles); DDX_Control(pDX, TAB_ACTION, m_tabAction); DDX_Control(pDX, LST_TARGETFILES, m_lstTargetFiles); DDX_Control(pDX, LST_SOURCEFILES, m_lstSourceFiles); DDX_Control(pDX, PRG_PROGRESS, m_prgProgress); DDX_Check(pDX, CHK_RECURSEDIR, m_bRecurse); DDX_Radio(pDX, RAD_MATCHCRITERIA, m_nMatchCriteria); DDX_Text(pDX, EDT_UPTO, m_dwUpto); DDX_Text(pDX, EDT_ALLOWEDMASKS, m_strAllowedMasks); DDX_Text(pDX, EDT_DIRECTORY, m_strDirectory); DDX_Check(pDX, CHK_COMPAREDUPLICATES, m_bCompareDuplicates); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CFCompareDlg, CDialog) //{{AFX_MSG_MAP(CFCompareDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(RAD_MATCHCONTENTS, OnMatchContents) ON_BN_CLICKED(RAD_MATCHCRITERIA, OnMatchCriteria) ON_BN_CLICKED(BTN_COMPARE, OnCompare) ON_WM_TIMER() ON_NOTIFY(LVN_GETDISPINFO, LST_SOURCEFILES, OnGetdispinfoSearchFiles) ON_BN_CLICKED(BTN_EXIT, OnExit) ON_NOTIFY(TCN_SELCHANGE, TAB_ACTION, OnSelchangeAction) ON_NOTIFY(LVN_GETDISPINFO, LST_MATCHEDFILES, OnGetdispinfoMatchedFiles) ON_BN_CLICKED(BTN_EXPLOREDIR, OnExploreDirectory) ON_BN_CLICKED(BTN_ADDSOURCEFILES, OnAddSourceFiles) ON_BN_CLICKED(BTN_ADDTARGETFILES, OnAddTargetFiles) ON_BN_CLICKED(BTN_CLEARSOURCEFILES, OnClearSourceFiles) ON_BN_CLICKED(BTN_CLEARTARGETFILES, OnClearTargetFiles) ON_WM_CLOSE() ON_NOTIFY(LVN_GETDISPINFO, LST_TARGETFILES, OnGetdispinfoSearchFiles) ON_BN_CLICKED(RAD_MATCHCHECKSUM, OnMatchContents) ON_BN_CLICKED(RAD_MATCHCRC, OnMatchContents) ON_BN_CLICKED(BTN_EXPORT, OnExport) //}}AFX_MSG_MAP ON_MESSAGE(WM_SEARCH_FINISHED, OnSearchFinished) ON_MESSAGE(WM_COMPARE_FINISHED, OnCompareFinished) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CFCompareDlg message handlers BOOL CFCompareDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } // Invalidate maximize & resize pSysMenu->EnableMenuItem(SC_SIZE,MF_GRAYED); pSysMenu->EnableMenuItem(SC_MAXIMIZE,MF_GRAYED); pSysMenu->EnableMenuItem(SC_RESTORE,MF_GRAYED); } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon m_lstSourceFiles.InsertColumn(0,_T("Filename"),LVCFMT_LEFT,300); m_lstSourceFiles.InsertColumn(1,_T("Size"),LVCFMT_RIGHT,65); m_lstTargetFiles.InsertColumn(0,_T("Filename"),LVCFMT_LEFT,300); m_lstTargetFiles.InsertColumn(1,_T("Size"),LVCFMT_RIGHT,65); m_lstMatchedFiles.InsertColumn(0,_T("Source Filename"),LVCFMT_LEFT,268); m_lstMatchedFiles.InsertColumn(1,_T("Target Filename"),LVCFMT_LEFT,268); m_lstMatchedFiles.InsertColumn(2,_T("Size"),LVCFMT_RIGHT,65); UpdateCounters(); m_tabAction.InsertItem(PPG_SEARCH,_T(" Search ")); m_tabAction.InsertItem(PPG_COMPARE,_T(" Compare ")); GetDlgItem(LBL_TARGETFILES)->ShowWindow(SW_SHOW); GetDlgItem(LBL_SOURCEFILES)->ShowWindow(SW_SHOW); GetDlgItem(LST_TARGETFILES)->ShowWindow(SW_SHOW); GetDlgItem(LST_SOURCEFILES)->ShowWindow(SW_SHOW); GetDlgItem(CHK_RECURSEDIR)->ShowWindow(SW_SHOW); GetDlgItem(BTN_COMPARE)->ShowWindow(SW_SHOW); GetDlgItem(LBL_MATCHEDFILES)->ShowWindow(SW_HIDE); GetDlgItem(LST_MATCHEDFILES)->ShowWindow(SW_HIDE); UpdateData(FALSE); return TRUE; // return TRUE unless you set the focus to a control } void CFCompareDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CFCompareDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CFCompareDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CFCompareDlg::OnExploreDirectory() { CDirDialog dlgDir; dlgDir.m_strTitle = _T("Select directory for file search"); UpdateData(TRUE); dlgDir.m_strSelDir = m_strDirectory; dlgDir.m_strWindowTitle = _T("Select directory"); if (dlgDir.DoBrowse(this) == IDOK) { m_strDirectory = dlgDir.m_strPath; // Append backslash if necessary if ((m_strDirectory.GetLength()>0) && (m_strDirectory[m_strDirectory.GetLength()-1] != TCHAR('\\'))) m_strDirectory += TCHAR('\\'); UpdateData(FALSE); } } void CFCompareDlg::OnMatchContents() { GetDlgItem(EDT_UPTO)->EnableWindow(TRUE); } void CFCompareDlg::OnMatchCriteria() { GetDlgItem(EDT_UPTO)->EnableWindow(FALSE); } UINT SearchThread(CFCompareDlg *pcdlg) { // Retrieve directories LVITEM lvi; CString strMask; int nPos=0; int nNextPos=0; memset(&lvi,0,sizeof(lvi)); pcdlg->m_bAddInProgress = TRUE; // Delete files' listview (if files were added, listviews are no longer up to date due // to possible reordering of items in FileInfoArray). pcdlg->m_plstFiles->DeleteAllItems(); // Retrieve files: Sorted by size and ascending, do not include dirs. while (nPos < pcdlg->m_strAllowedMasks.GetLength()) { nNextPos = pcdlg->m_strAllowedMasks.Find(";",nPos); if (nNextPos == -1) nNextPos = pcdlg->m_strAllowedMasks.GetLength(); strMask = pcdlg->m_strAllowedMasks.Mid(nPos, nNextPos-nPos); strMask.TrimLeft(); strMask.TrimRight(); TRACE("strMask is %s\n",strMask); if (strMask != "") pcdlg->m_pfiaInfos->AddDir(pcdlg->m_strDirectory, strMask, pcdlg->m_bRecurse, CFileInfoArray::AP_SORTBYSIZE | CFileInfoArray::AP_SORTASCENDING, FALSE, &pcdlg->m_bAbort); nPos = nNextPos+1; } pcdlg->m_lblStatus.SetWindowText(_T("Filling listview...")); pcdlg->m_ulProgress = 0; pcdlg->m_ulProgressMax = pcdlg->m_pfiaInfos->GetSize(); pcdlg->m_bAddInProgress = FALSE; pcdlg->m_bFillInProgress = TRUE; // Set common LVITEM attributes lvi.pszText = LPSTR_TEXTCALLBACK; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iSubItem = 0; // Insert files pcdlg->m_plstFiles->LockWindowUpdate(); for (int i=0;((i<pcdlg->m_pfiaInfos->GetSize()) && (!pcdlg->m_bAbort));i++) { lvi.iItem = i; lvi.lParam = (LPARAM) &(*pcdlg->m_pfiaInfos)[i]; pcdlg->m_plstFiles->InsertItem(&lvi); pcdlg->m_ulProgress++; } pcdlg->m_plstFiles->UnlockWindowUpdate(); pcdlg->m_bFillInProgress = FALSE; pcdlg->PostMessage(WM_SEARCH_FINISHED); return 0; } BOOL CompareContents(CFileInfo* pfinSrc, CFileInfo* pfinDest, const DWORD dwUpTo, volatile BOOL* pbAbort) { // Note this method is not "win64 friendly" FILE* fSrc; FILE* fDest; DWORD dwCount = 0; BYTE cSrc, cDest; if ((dwUpTo == 0) || (dwUpTo > pfinSrc->GetLength())) dwCount = pfinSrc->GetLength(); else dwCount = dwUpTo; fSrc = fopen(pfinSrc->GetFilePath(),"rb"); fDest = fopen(pfinDest->GetFilePath(),"rb"); if (fSrc && fDest) { while (!feof(fSrc) && !feof(fDest) && !(*pbAbort) && (dwCount>0) && fread(&cSrc,1,1,fSrc) && fread(&cDest,1,1,fDest) && (cSrc == cDest)) { dwCount--; } } if (fSrc) fclose(fSrc); if (fDest) fclose(fDest); return (dwCount == 0); } UINT CompareThread(CFCompareDlg *pcdlg) { CFileInfo* pfinSource; CFileInfo* pfinTarget; MATCHSTRUCT ms; DWORD dwMatchSize=0; DWORD dwMatchNumber=0; LVITEM lviMatched; // Compare int iSource=0; int iTarget=0; pcdlg->m_bCompareInProgress = TRUE; pcdlg->m_ulProgress = 0; pcdlg->m_ulProgressMax = pcdlg->m_fiaSourceInfos.GetSize() + pcdlg->m_fiaTargetInfos.GetSize(); while ((!pcdlg->m_bAbort) && (iSource<pcdlg->m_fiaSourceInfos.GetSize()) && (iTarget<pcdlg->m_fiaTargetInfos.GetSize())) { pfinSource = &pcdlg->m_fiaSourceInfos[iSource]; pfinTarget = &pcdlg->m_fiaTargetInfos[iTarget]; // Compare pfinSource with all the files of target with the same size of pfinSource for (int i=iTarget;(i<pcdlg->m_fiaTargetInfos.GetSize()) && (pcdlg->m_fiaTargetInfos[i].GetLength64() == pfinSource->GetLength64());i++) { pfinTarget = &pcdlg->m_fiaTargetInfos[i]; if (// Not the same file or Ignore duplicates unchecked (pcdlg->m_bCompareDuplicates || (pfinSource->GetFilePath().CompareNoCase(pfinTarget->GetFilePath()) != 0)) && // Checksum criteria ((pcdlg->m_nMatchCriteria != 1) || (pfinSource->GetChecksum(pcdlg->m_dwUpto, FALSE, &pcdlg->m_bAbort) == pfinTarget->GetChecksum(pcdlg->m_dwUpto, FALSE, &pcdlg->m_bAbort))) && // CRC criteria ((pcdlg->m_nMatchCriteria != 2) || (pfinSource->GetCRC(pcdlg->m_dwUpto, FALSE, &pcdlg->m_bAbort) == pfinTarget->GetCRC(pcdlg->m_dwUpto, FALSE, &pcdlg->m_bAbort))) && // Contents criteria ((pcdlg->m_nMatchCriteria != 3) || (CompareContents(pfinSource, pfinTarget, pcdlg->m_dwUpto, &pcdlg->m_bAbort))) ) { // Match! ms.pfinTarget = pfinTarget; ms.pfinSource = pfinSource; pcdlg->m_msaMatchedInfos.InsertAt(pcdlg->m_msaMatchedInfos.GetSize(), ms); dwMatchSize += pfinTarget->GetLength(); dwMatchNumber++; } } // Restore initial target pfinTarget = &pcdlg->m_fiaTargetInfos[iTarget]; if (pfinTarget->GetLength64() >= pfinSource->GetLength64()) iSource++; // In case of equal sizes, iSource must be incremented first // (see inner loop for reasons) else iTarget++; pcdlg->m_ulProgress++; } // Set new progress values pcdlg->m_ulProgress = 0; pcdlg->m_ulProgressMax = pcdlg->m_msaMatchedInfos.GetSize(); pcdlg->m_bCompareInProgress = FALSE; pcdlg->m_bFillInProgress = TRUE; // Fill listview pcdlg->m_lblStatus.SetWindowText(_T("Filling listview...")); pcdlg->m_lstMatchedFiles.LockWindowUpdate(); // Set common LVITEM values for all elements lviMatched.mask = LVIF_PARAM | LVIF_TEXT; lviMatched.iSubItem = 0; lviMatched.pszText = LPSTR_TEXTCALLBACK; for (int i=0;(i<pcdlg->m_msaMatchedInfos.GetSize()) && (!pcdlg->m_bAbort);i++) { lviMatched.iItem = i; lviMatched.lParam = (LPARAM) &pcdlg->m_msaMatchedInfos[i]; pcdlg->m_lstMatchedFiles.InsertItem(&lviMatched); pcdlg->m_ulProgress++; } pcdlg->m_lstMatchedFiles.UnlockWindowUpdate(); pcdlg->m_bFillInProgress = FALSE; // Report compare thread end pcdlg->PostMessage(WM_COMPARE_FINISHED,dwMatchNumber, dwMatchSize); return 0; } void CFCompareDlg::SetBusyState(int m_bsState) { this->m_bsState = m_bsState; GetDlgItem(LST_SOURCEFILES)->EnableWindow(m_bsState != BS_SEARCHING); GetDlgItem(LST_TARGETFILES)->EnableWindow(m_bsState != BS_SEARCHING); GetDlgItem(CHK_RECURSEDIR)->EnableWindow(m_bsState != BS_SEARCHING); GetDlgItem(BTN_COMPARE)->EnableWindow(m_bsState == BS_IDLE); GetDlgItem(BTN_CLEARSOURCEFILES)->EnableWindow(m_bsState == BS_IDLE); GetDlgItem(BTN_CLEARTARGETFILES)->EnableWindow(m_bsState == BS_IDLE); GetDlgItem(BTN_ADDSOURCEFILES)->EnableWindow(m_bsState == BS_IDLE); GetDlgItem(BTN_ADDTARGETFILES)->EnableWindow(m_bsState == BS_IDLE); GetDlgItem(BTN_EXPORT)->EnableWindow(m_bsState == BS_IDLE); GetDlgItem(RAD_MATCHCRITERIA)->EnableWindow(m_bsState != BS_COMPARING); GetDlgItem(RAD_MATCHCHECKSUM)->EnableWindow(m_bsState != BS_COMPARING); GetDlgItem(RAD_MATCHCRC)->EnableWindow(m_bsState != BS_COMPARING); GetDlgItem(RAD_MATCHCONTENTS)->EnableWindow(m_bsState != BS_COMPARING); GetDlgItem(EDT_UPTO)->EnableWindow((m_bsState != BS_COMPARING) && (IsDlgButtonChecked(RAD_MATCHCRITERIA) != BST_CHECKED)); GetDlgItem(CHK_COMPAREDUPLICATES)->EnableWindow(m_bsState != BS_COMPARING); if (m_bsState != BS_IDLE) { GetDlgItem(BTN_EXIT)->SetWindowText(_T("Cancel")); } else { GetDlgItem(BTN_EXIT)->SetWindowText(_T("Exit")); m_lblStatus.SetWindowText(_T("Ready")); m_prgProgress.SetPos(0); } } void CFCompareDlg::UpdateCounters() { CString str; str.Format(_T("Matched files (%d)"), m_lstMatchedFiles.GetItemCount()); GetDlgItem(LBL_MATCHEDFILES)->SetWindowText(str); str.Format(_T("Source files (%d)"), m_lstSourceFiles.GetItemCount()); GetDlgItem(LBL_SOURCEFILES)->SetWindowText(str); str.Format(_T("Target files (%d)"), m_lstTargetFiles.GetItemCount()); GetDlgItem(LBL_TARGETFILES)->SetWindowText(str); } void CFCompareDlg::OnCompare() { // Retrieve comparison settings UpdateData(TRUE); m_lblStatus.SetWindowText(_T("Comparing files...")); // Empty compare list m_lstMatchedFiles.DeleteAllItems(); m_msaMatchedInfos.RemoveAll(); m_bAbort = FALSE; SetBusyState(BS_COMPARING); // Launch thread AfxBeginThread((AFX_THREADPROC) CompareThread,(LPVOID) this); // Launch progress-report timer if (SetTimer(1,250, NULL) == 0){ // Timer not available AfxMessageBox(_T("Timer is not available, real time progress will not be reported."), MB_ICONINFORMATION | MB_OK); } } void CFCompareDlg::OnGetdispinfoSearchFiles(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; CString str; CFileInfo* pinf; pinf = (CFileInfo*) pDispInfo->item.lParam; switch (pDispInfo->item.iSubItem) { case 0: pDispInfo->item.mask = LVIF_TEXT; StrCpyN(pDispInfo->item.pszText, pinf->GetFilePath(), pDispInfo->item.cchTextMax); break; case 1: if (pinf->GetLength64() < 1024) str.Format("%d B", pinf->GetLength()); else { // The following weird LONGLONG casts are because VC 6.0 doesn't implement int64 // to double conversion =8-ooo if (pinf->GetLength64() < (1024*1024)) str.Format("%3.2f KB",(LONGLONG) pinf->GetLength64() / 1024.0); else { if (pinf->GetLength64() < (1024*1024*1024)) str.Format("%3.2f MB", (LONGLONG) pinf->GetLength64() / (1024*1024.0)); else str.Format("%1.2f GB", (LONGLONG) pinf->GetLength64() / (1024.0*1024*1024)); } } pDispInfo->item.mask = LVIF_TEXT; StrCpyN(pDispInfo->item.pszText, str, pDispInfo->item.cchTextMax); break; } *pResult = 0; } void CFCompareDlg::OnTimer(UINT nIDEvent) { CString str; if (m_bAddInProgress) { str.Format(_T("Found %d files"),m_fiaSourceInfos.GetSize() + m_fiaTargetInfos.GetSize()); m_lblStatus.SetWindowText(str); str.Format(_T("Source files (%d)"), m_fiaSourceInfos.GetSize()); m_lblSourceFiles.SetWindowText(str); str.Format(_T("Target files (%d)"), m_fiaTargetInfos.GetSize()); m_lblTargetFiles.SetWindowText(str); } if (m_bFillInProgress) { m_prgProgress.SetRange(0, (short) m_ulProgressMax); m_prgProgress.SetPos(m_ulProgress); } if (m_bCompareInProgress) { str.Format(_T("Matched %d files"), m_msaMatchedInfos.GetSize()); m_lblStatus.SetWindowText(str); str.Format(_T("Matched files (%d)"), m_msaMatchedInfos.GetSize()); m_lblMatchedFiles.SetWindowText(str); m_prgProgress.SetRange(0, (short) m_ulProgressMax); m_prgProgress.SetPos(m_ulProgress); } CDialog::OnTimer(nIDEvent); } afx_msg LONG CFCompareDlg::OnSearchFinished(WPARAM /* wparam*/ , LPARAM /* lparam */) { if (m_bAbort) { // Delete items from aborted listview m_plstFiles->DeleteAllItems(); // Delete items from aborted CFileInfoArray m_pfiaInfos->RemoveAll(); } KillTimer(1); SetBusyState(BS_IDLE); m_lblStatus.SetWindowText(_T("Ready")); UpdateCounters(); if (m_bExit) PostQuitMessage(0); return TRUE; } afx_msg LONG CFCompareDlg::OnCompareFinished(WPARAM wparam, LPARAM lparam) { CString str; if (m_bAbort) m_lstMatchedFiles.DeleteAllItems(); KillTimer(1); SetBusyState(BS_IDLE); if (!m_bAbort) { str.Format(_T("Comparison results:\r\n* %d files matched\r\n* %d bytes matched"), wparam, lparam); MessageBox(str,_T("Comparison ended"),MB_OK); } m_prgProgress.SetPos(0); str.Format(_T("Matched files (%d)"),m_lstMatchedFiles.GetItemCount()); m_lblMatchedFiles.SetWindowText(str); UpdateCounters(); if (m_bExit) PostQuitMessage(0); return TRUE; } void CFCompareDlg::OnExit() { if (m_bsState == BS_IDLE) PostQuitMessage(0); m_bAbort = TRUE; } void CFCompareDlg::OnSelchangeAction(NMHDR* /* pNMHDR*/, LRESULT* pResult) { if (m_tabAction.GetCurSel() == PPG_COMPARE) { GetDlgItem(LBL_TARGETFILES)->ShowWindow(SW_HIDE); GetDlgItem(LBL_SOURCEFILES)->ShowWindow(SW_HIDE); GetDlgItem(LST_TARGETFILES)->ShowWindow(SW_HIDE); GetDlgItem(LST_SOURCEFILES)->ShowWindow(SW_HIDE); GetDlgItem(BTN_COMPARE)->ShowWindow(SW_HIDE); GetDlgItem(LBL_MATCHEDFILES)->ShowWindow(SW_SHOW); GetDlgItem(LST_MATCHEDFILES)->ShowWindow(SW_SHOW); GetDlgItem(CHK_COMPAREDUPLICATES)->ShowWindow(SW_HIDE); } else { GetDlgItem(LBL_TARGETFILES)->ShowWindow(SW_SHOW); GetDlgItem(LBL_SOURCEFILES)->ShowWindow(SW_SHOW); GetDlgItem(LST_TARGETFILES)->ShowWindow(SW_SHOW); GetDlgItem(LST_SOURCEFILES)->ShowWindow(SW_SHOW); GetDlgItem(BTN_COMPARE)->ShowWindow(SW_SHOW); GetDlgItem(LBL_MATCHEDFILES)->ShowWindow(SW_HIDE); GetDlgItem(LST_MATCHEDFILES)->ShowWindow(SW_HIDE); GetDlgItem(CHK_COMPAREDUPLICATES)->ShowWindow(SW_SHOW); } *pResult = 0; } void CFCompareDlg::OnGetdispinfoMatchedFiles(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; MATCHSTRUCT* pms; CFileInfo* pinf; CString str; switch (pDispInfo->item.iSubItem) { case 0: pDispInfo->item.mask = LVIF_TEXT; pms = (MATCHSTRUCT*) pDispInfo->item.lParam; StrCpyN(pDispInfo->item.pszText, pms->pfinSource->GetFilePath(), pDispInfo->item.cchTextMax); break; case 1: pDispInfo->item.mask = LVIF_TEXT; pms = (MATCHSTRUCT*) pDispInfo->item.lParam; StrCpyN(pDispInfo->item.pszText, pms->pfinTarget->GetFilePath(), pDispInfo->item.cchTextMax); break; case 2: pms = (MATCHSTRUCT*) pDispInfo->item.lParam; pinf = pms->pfinSource; if (pinf->GetLength64() < 1024) str.Format("%d B",pinf->GetLength()); else { // The following weird LONGLONG casts are because VC 6.0 doesn't implement int64 // to double conversion =8-ooo if (pinf->GetLength64() < (1024*1024)) str.Format("%3.2f KB",(LONGLONG) pinf->GetLength64() / 1024.0); else { if (pinf->GetLength64() < (1024*1024*1024)) str.Format("%3.2f MB", (LONGLONG) pinf->GetLength64() / (1024*1024.0)); else str.Format("%1.2f GB", (LONGLONG) pinf->GetLength64() / (1024.0*1024*1024)); } } pDispInfo->item.mask = LVIF_TEXT; StrCpyN(pDispInfo->item.pszText, str, pDispInfo->item.cchTextMax); break; } *pResult = 0; } void CFCompareDlg::OnAddSourceFiles() { // Retrieve search settings from dialog controls UpdateData(TRUE); // Append backslash if necessary if ((m_strDirectory.GetLength()>0) && (m_strDirectory[m_strDirectory.GetLength()-1] != TCHAR('\\'))) m_strDirectory += TCHAR('\\'); UpdateData(FALSE); // Set common variables with thread m_plstFiles = &m_lstSourceFiles; m_pfiaInfos = &m_fiaSourceInfos; // Compare text-callback list will no longer be up to date, empty it m_lstMatchedFiles.DeleteAllItems(); m_msaMatchedInfos.RemoveAll(); m_lblStatus.SetWindowText(_T("Inserting files...")); m_bAbort = FALSE; SetBusyState(BS_SEARCHING); // Launch thread AfxBeginThread((AFX_THREADPROC) SearchThread,(LPVOID) this); // Launch progress-report timer if (SetTimer(1,250, NULL) == 0){ // Timer not available AfxMessageBox(_T("Timer is not available, real time progress will not be reported."), MB_ICONINFORMATION | MB_OK); } } void CFCompareDlg::OnAddTargetFiles() { // Retrieve search settings from dialog controls UpdateData(TRUE); // Append backslash if necessary if ((m_strDirectory.GetLength()>0) && (m_strDirectory[m_strDirectory.GetLength()-1] != TCHAR('\\'))) m_strDirectory += TCHAR('\\'); UpdateData(FALSE); // Set common variables with thread m_plstFiles = &m_lstTargetFiles; m_pfiaInfos = &m_fiaTargetInfos; // Compare text-callback list will no longer be up to date, empty it m_lstMatchedFiles.DeleteAllItems(); m_msaMatchedInfos.RemoveAll(); m_lblStatus.SetWindowText(_T("Inserting files...")); m_bAbort = FALSE; SetBusyState(BS_SEARCHING); // Launch thread AfxBeginThread((AFX_THREADPROC) SearchThread,(LPVOID) this); // Launch progress-report timer if (SetTimer(1,250, NULL) == 0){ // Timer not available AfxMessageBox(_T("Timer is not available, real time progress will not be reported."), MB_ICONINFORMATION | MB_OK); } } void CFCompareDlg::OnClearSourceFiles() { // Clear matched m_lstMatchedFiles.DeleteAllItems(); m_msaMatchedInfos.RemoveAll(); // Clear listview m_lstSourceFiles.DeleteAllItems(); // Clear fileinfos array m_fiaSourceInfos.RemoveAll(); // UpdateCounters UpdateCounters(); } void CFCompareDlg::OnClearTargetFiles() { // Clear matched m_lstMatchedFiles.DeleteAllItems(); m_msaMatchedInfos.RemoveAll(); // Clear listview m_lstTargetFiles.DeleteAllItems(); // Clear fileinfos array m_fiaTargetInfos.RemoveAll(); // Update counters UpdateCounters(); } void CFCompareDlg::OnClose() { if (m_bsState != BS_IDLE) { // Thread running, signal abort and exit flag m_bExit = TRUE; m_bAbort = TRUE; } else CDialog::OnClose(); } void CFCompareDlg::OnExport() { CStdioFile sf; CFileDialog fd(FALSE); int i; CString str; if (fd.DoModal() == IDOK) { try { sf.Open(fd.m_ofn.lpstrFile, CStdioFile::modeWrite | CFile::modeCreate | CStdioFile::typeText); sf.WriteString(_T("SOURCE FILES:\n")); for (i=0;i<m_fiaSourceInfos.GetSize();i++) sf.WriteString("\""+m_fiaSourceInfos[i].GetFilePath() + "\"\n"); sf.WriteString(_T("TARGET FILES:\n")); for (i=0;i<m_fiaTargetInfos.GetSize();i++) sf.WriteString("\"" + m_fiaTargetInfos[i].GetFilePath() + "\"\n"); sf.WriteString(_T("MATCHED FILES:\n")); for (i=0;i<m_msaMatchedInfos.GetSize();i++) sf.WriteString("\"" + m_msaMatchedInfos[i].pfinSource->GetFilePath() + "\"" + " \\ " + "\"" + m_msaMatchedInfos[i].pfinTarget->GetFilePath() + "\"\n"); sf.Close(); } catch (CException e) { e.Delete(); } } }